package xinhao.ll;

import xinhao.Alphabet;
import xinhao.Grammar;
import xinhao.Production;
import xinhao.Symbol;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author by xinhao  2021/8/13
 */
public class Test {

    private static void testLeftRecursion() {
        Symbol start = Alphabet.getSymbol('S');
        List<Production> productions = new ArrayList<>();
        productions.addAll(Production.createList(start, "Aa", "b", "ε"));
        productions.addAll(Production.createList(Alphabet.getSymbol('A'), "Ac", "Sd"));
        Grammar grammar = Grammar.create(start, productions);
        Grammar indirectGrammar =  GrammarUtils.eliminateIndirectLeftRecursion(grammar);
        Grammar deepGrammar =  GrammarUtils.eliminateDeepLeftRecursion(indirectGrammar);
        System.out.println(grammar);
        System.out.println(indirectGrammar);
        System.out.println(deepGrammar);
    }

    private static void testSelect() {
        Symbol start = Alphabet.getSymbol('E');
        List<Production> productions = new ArrayList<>();

        productions.addAll(Production.createList(start, "E+T", "T"));
        productions.addAll(Production.createList(Alphabet.getSymbol('T'), "T*F", "F"));
        productions.addAll(Production.createList(Alphabet.getSymbol('F'), "(E)", "d"));

        Grammar grammar = Grammar.create(start, productions);

        Grammar deepGrammar = GrammarUtils.eliminateDeepLeftRecursion(grammar);
        Map<Symbol, FirstSet> firstSetMap = deepGrammar.getFirstSetMap();
        Map<Symbol, FollowSet> followSetMap = deepGrammar.getFollowSetMap();

        List<SelectSet> selectSetList = GrammarUtils.getAllSelectSetByGrammar(deepGrammar);
        Map<Symbol, Map<Symbol, Production>> table = GrammarUtils.listToSelectTable(selectSetList);


        List<Symbol> matchSymbols = new ArrayList<>();
        matchSymbols.add(Alphabet.getSymbol('d'));
        matchSymbols.add(Alphabet.getSymbol('+'));
        matchSymbols.add(Alphabet.getSymbol('d'));
        matchSymbols.add(Alphabet.getSymbol('*'));
        matchSymbols.add(Alphabet.getSymbol('d'));
        matchSymbols.add(Symbol.END);
        List<Production> matchProductionList = GrammarUtils.match(deepGrammar.getStart(), table, matchSymbols);


        System.out.println("原始的文法:");
        System.out.println(grammar);
        System.out.println();

        System.out.println("去除左递归之后的文法:");
        System.out.println(deepGrammar);
        System.out.println();

        System.out.println("文法first集和follow集:");
        deepGrammar.getProductionsMap().keySet().forEach(symbol ->
                System.out.println(firstSetMap.get(symbol) +"\t\t" + followSetMap.get(symbol)));
        System.out.println();


        System.out.println("文法产生式的可选集:");
        selectSetList.forEach(selectSet -> System.out.println(selectSet));
        System.out.println();

        System.out.println("匹配 d+d*d 的产生组:");
        System.out.println(matchProductionList);
    }

    public static void main(String[] args) {

//        Grammar grammar = Grammar.create(Alphabet.getSymbol("S"),
//                Production.createList(Alphabet.getSymbol("S"), "aaB", "aaC","aaaD","d"));
////                Production.createList(Alphabet.getSymbol("S"), "bbB","aaB", "ccC","aaaC", "bbbD","ccD","aaaD", "bbD","d"));
//
//        System.out.println(grammar);
//        GrammarUtils.extractLeftCommonFactor(grammar);


//        testLeftRecursion();
        testSelect();
    }
}
